package render;

import java.util.HashMap;
import java.util.Map;

import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Light;
import javax.media.j3d.Node;
import javax.media.j3d.PointLight;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.geometry.Sphere;

public abstract class LightingSetup {

	protected Map<String, Light> lights;
	protected static final String NODE_LIGHT_ = "NODE_LIGHT_";
	protected boolean renderPointLights = false;
	protected Bounds scenarioBounds;
	
	public LightingSetup()
	{
		lights = new HashMap<String, Light>();
	}
	
	public Map<String, Light> getLights()
	{
		return lights;
	}
	
	public void setup(Bounds lightBounds)
	{
		
	}
	
	public void updateLights(Bounds lightBounds)
	{
		scenarioBounds = lightBounds;
		
	}
	
	public void renderPointLights(boolean renderPointLights)
	{
		this.renderPointLights = renderPointLights;
	}
	
	protected void setDirectionalLigthCapabilities(DirectionalLight directionalLight)
	{
		directionalLight.setCapability(Node.ALLOW_BOUNDS_READ);
		directionalLight.setCapability(DirectionalLight.ALLOW_STATE_READ);
		directionalLight.setCapability(DirectionalLight.ALLOW_STATE_WRITE);
		directionalLight.setCapability(DirectionalLight.ALLOW_INFLUENCING_BOUNDS_READ);
		directionalLight.setCapability(DirectionalLight.ALLOW_INFLUENCING_BOUNDS_WRITE);
	}
	
	protected void setPointLigthCapabilities(PointLight pointLight)
	{
		pointLight.setCapability(Node.ALLOW_BOUNDS_READ);
		pointLight.setCapability(PointLight.ALLOW_STATE_READ);
		pointLight.setCapability(PointLight.ALLOW_STATE_WRITE);
		pointLight.setCapability(PointLight.ALLOW_POSITION_READ);
		pointLight.setCapability(PointLight.ALLOW_POSITION_WRITE);
		pointLight.setCapability(PointLight.ALLOW_INFLUENCING_BOUNDS_READ);
		pointLight.setCapability(PointLight.ALLOW_INFLUENCING_BOUNDS_WRITE);
	}
	
	public BranchGroup renderPointLights()
	{
		float size = (float) (((BoundingSphere)scenarioBounds).getRadius() * 0.05);
		BranchGroup lightingPoints = new BranchGroup();
		NodeCharacteristics.setBranchGroupCapabilities(lightingPoints);
		if(renderPointLights)
		{
			for(Map.Entry<String, Light> entry : lights.entrySet())
			{
				Light l = entry.getValue();
				BoundingSphere lBounds = (BoundingSphere)l.getInfluencingBounds();
				Point3d lBoundsCenter = new Point3d();
				lBounds.getCenter(lBoundsCenter);
				if( l instanceof PointLight)
				{
					Point3f lightPosition = new Point3f();
					((PointLight) l).getPosition(lightPosition);
					Sphere lightPositionSphere = new Sphere(size);
					
					Sphere lightBoundsSphere = new Sphere((float)lBounds.getRadius());
					Appearance lBApp = new Appearance();
					PolygonAttributes lbPatt = new PolygonAttributes();
					lbPatt.setPolygonMode(PolygonAttributes.POLYGON_LINE);
					lBApp.setPolygonAttributes(lbPatt);
					lightBoundsSphere.setAppearance(lBApp);
					ColoringAttributes colAtt = new ColoringAttributes();
					colAtt.setColor(0, 0, 0);
					lBApp.setColoringAttributes(colAtt);
					
					BranchGroup lightPositionBG = new BranchGroup();
					TransformGroup lightPositionTG = new TransformGroup();
					Transform3D lightPositionT3d = new Transform3D();
					lightPositionT3d.setTranslation(new Vector3d(lBoundsCenter));
					lightPositionTG.setTransform(lightPositionT3d);
					lightPositionTG.addChild(lightPositionSphere);
					lightPositionTG.addChild(lightBoundsSphere);
					lightPositionBG.addChild(lightPositionTG);
					lightingPoints.addChild(lightPositionBG);
				}
			}
		}
		return lightingPoints;
	}
}
